import re
import uuid

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import serializers
from user.models import User, OAuthUser, UserAuth
from django_redis import get_redis_connection
import snowflake.client
from dingxiang_doctor.utils.myredis import r

# 自定义载荷信息
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token["username"] = str(user.username)
        token["password"] = str(user.password)
        token["mobile"] = str(user.mobile)
        token["email"] = str(user.email)
        return token

class UserRegisterSerializer(serializers.ModelSerializer):
    re_password = serializers.CharField(write_only=True, required=True)

    gender_display = serializers.CharField(source="get_gender_display", read_only=True)
    token = serializers.CharField(read_only=True)
    refresh = serializers.CharField(read_only=True)

    class Meta:
        model = User
        fields = ["username", "password", "re_password", "mobile", "email", "gender", "gender_display", "avatar", "age",
                  "token", "refresh"]

    def validate(self, attrs):
        # 验证密码
        password = attrs.get("password", None)
        re_password = attrs.get("re_password", None)
        if password != re_password:
            raise serializers.ValidationError(detail="两次密码不一致", code=400)

        # 验证手机号和邮箱号
        mobile = attrs.get("mobile", None)
        # 如果手机号不为None且不符合正则规范
        if mobile is not None and not re.match(r"^1[3-9]\d{9}$", mobile):
            raise serializers.ValidationError(detail="手机号格式错误", code=400)
        email = attrs.get("email", None)
        # @前匹配6-14位数字字母下划线 @后可以匹配qq、163、139、sina，固定以.com结尾
        if email is not None and not re.match(r"^[0-9a-z_]{6,14}@(qq|163|139|sina)\.com$", email):
            raise serializers.ValidationError(detail="邮箱号格式错误", code=400)

        # 验证用户名不能重复，且防止修改时自我冲突
        request = self.context["request"]
        origin_username = request.user.username
        print(origin_username)
        username = attrs.get("username", None)
        if origin_username != username:
            if User.objects.filter(username=username):
                raise serializers.ValidationError(detail="用户名不能重复", code=400)

        # 生成snowflake id
        last_snow_id = int(r.get_str("snow_id"))
        for i in range(3):
            snow_id = snowflake.client.get_guid()
            if snow_id > last_snow_id:
                break
            if i == 2:
                # 重新设置服务器时间
                pass
        snow_id = snowflake.client.get_guid()
        attrs["snow_id"] = str(snow_id)
        r.set_str("snow_id", str(snow_id))

        if attrs.get("re_password"):
            attrs.pop("re_password")

        return attrs

    def create(self, validated_data):
        user = User.objects.create_user(
            username=validated_data.get("username"),
            password=validated_data.get("password"),
            mobile=validated_data.get("mobile", None),
            email=validated_data.get("email", None),
            snow_id=validated_data.get("snow_id"),
        )

        # 自定义token
        refresh = CustomTokenObtainPairSerializer.get_token(user)
        user.refresh = str(refresh)
        user.token = str(refresh.access_token)

        return user

class SmsRegisterSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(write_only=True, required=True)

    token = serializers.CharField(read_only=True)
    refresh = serializers.CharField(read_only=True)

    class Meta:
        model = User
        fields = ["mobile", "sms_code", "token", "refresh"]

    def validate(self, attrs):
        # 判断验证码是否输入正确
        mobile = attrs.get("mobile")
        sms_code = attrs.get("sms_code")
        redis = get_redis_connection("sms_code")
        code = redis.get(f"dingxiang_sms_{mobile}")
        if code is None:
            raise serializers.ValidationError(detail="验证码已过期，请重新获取", code=400)
        code = code.decode()
        if sms_code != code:
            raise serializers.ValidationError(detail="验证码输入错误，请重新输入", code=400)
        # 校验成功后删除字段
        redis.delete(f"dingxiang_sms_{mobile}")

        # 生成snowflake id
        last_snow_id = int(r.get_str("user_id"))
        for i in range(3):
            snow_id = snowflake.client.get_guid()
            if snow_id > last_snow_id:
                break
            if i == 2:
                # 重新设置服务器时间
                pass
        snow_id = snowflake.client.get_guid()
        r.set_str("user_id", snow_id)
        attrs["snow_id"] = str(snow_id)

        attrs.pop("sms_code")

        return attrs

    def create(self, validated_data):
        # 使用验证码注册，用户名随机生成，密码为默认值123456
        mobile = validated_data.get("mobile")
        username = str(uuid.uuid4())
        user = User.objects.create_user(
            username=username,
            password="123456",
            mobile=mobile,
        )

        refresh = CustomTokenObtainPairSerializer.get_token(user)
        user.refresh = str(refresh)
        user.token = str(refresh.access_token)

        return user

# 第三方登录表序列化器
class OAuthUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = OAuthUser
        fields = "__all__"

# 用户实名认证表序列化器
class UserAuthSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserAuth
        fields = "__all__"
